/*
 ------------------------------------------------------------------------------
 Copyright (C) 2009-2011 Eternal Games.

 This file is part of the Eternal Tech source code.

 The Eternal Tech source code is free software; you can redistribute it and/or
 modify it under the terms of the GNU General Public License as published by
 the Free Software Foundation; either version 2 of the License, or (at your
 option) any later version.

 The Eternal Tech source code is distributed in the hope that it will be useful,
 but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
 or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
 more details.

 You should have received a copy of the GNU General Public License along with
 the Eternal Tech source code; if not, write to the Free Software Foundation, Inc.,
 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
 ------------------------------------------------------------------------------
*/


//
// s_main.cpp - Initializes the sound system
//


#include "s_local.h"


sndGlobals_t				snd;

cvar_t						*s_alDriver;
cvar_t						*s_deviceName;
cvar_t						*s_voiceCapture;
cvar_t						*s_captureDeviceName;

cvar_t						*s_logFile;
cvar_t						*s_ignoreALErrors;

cvar_t						*s_playDefaultSound;
cvar_t						*s_soundQuality;
cvar_t						*s_maxChannels;


/*
 ==============================================================================

    FUNCTIONS EXPORTED

 ==============================================================================
*/


/*
 ==================
 S_GetALConfig
 ==================
*/
alConfig_t S_GetALConfig ()
{
	return alConfig;
}

/*
 ==================
 S_Activate

 Called when the main window gains or loses focus.
 The window may have been destroyed and recreated between a deactivate and an
 activate.
 ==================
*/
void S_Activate (bool active)
{
	// TODO!!!
}


/*
 ==============================================================================

    CONSOLE COMMANDS

 ==============================================================================
*/


/*
 ==================
 S_ListSoundDevices_f
 ==================
*/
static void S_ListSoundDevices_f ()
{
	const char   *ptr = alConfig.deviceList;
	int			 count = 0;

	while (*ptr){
		Com_Printf("%s\n", ptr);

		ptr += Str_Length(ptr) + 1;
		count++;
	}

	Com_Printf("--------------------\n");
	Com_Printf("%i sound devices available\n", count);
}

/*
 ==================
 S_ListSoundCaptureDevices_f
 ==================
*/
static void S_ListSoundCaptureDevices_f ()
{
	const char   *ptr = alConfig.captureDeviceList;
	int			 count = 0;

	while (*ptr){
		Com_Printf("%s\n", ptr);

		ptr += Str_Length(ptr) + 1;
		count++;
	}

	Com_Printf("--------------------\n");
	Com_Printf("%i sound capture devices available\n", count);
}

/*
 ==================
 S_SfxInfo_f
 ==================
*/
static void S_SfxInfo_f ()
{
	Com_Printf("\n");
	Com_Printf("AL_VENDOR: %s\n", alConfig.vendorString);
	Com_Printf("AL_RENDERER: %s\n", alConfig.rendererString);
	Com_Printf("AL_VERSION: %s\n", alConfig.versionString);
	Com_Printf("AL_EXTENSIONS: %s\n", alConfig.extensionsString);
	Com_Printf("ALC_EXTENSIONS: %s\n", alConfig.alcExtensionsString);
	//Com_Printf("\n");
	//Com_Printf("AL_MAX_AUXILIARY_SENDS: %i\n", alConfig.maxAuxiliarySends);
	Com_Printf("\n");
	Com_Printf("DEVICE: %s\n", alConfig.deviceName);
	Com_Printf("CAPTURE DEVICE: %s\n", (alConfig.captureDeviceName) ? alConfig.captureDeviceName : "none");
	Com_Printf("MIXER: %i Hz (%s refresh)\n", alConfig.mixerFrequency, (alConfig.mixerSync) ? "synchronous" : Str_VarArgs("%i Hz", alConfig.mixerRefresh));
	Com_Printf("SOURCES: %i mono, %i stereo\n", alConfig.monoSources, alConfig.stereoSources);
	Com_Printf("CPU: %s\n", Win_GetProcessorString());
	Com_Printf("\n");
#if 0
	if (alConfig.efxAvailable)
	{
		if (snd.reverb.enabled)
			Com_Printf("Using reverb effects\n");
		else
			Com_Printf("Reverb effects are disabled\n");

		if (snd.filter.enabled)
			Com_Printf("Using low-pass filters\n");
		else
			Com_Printf("Low-pass filters are disabled\n");
	}
	else
	{
		Com_Printf("Reverb effects not available\n");
		Com_Printf("Low-pass filters not available\n");
	}

	if (alConfig.eaxRAMAvailable)
		Com_Printf("Using EAX-RAM (%.2f MB total, %.2f MB free)\n", qalGetInteger(AL_EAX_RAM_SIZE) * (1.0f / 1048576.0f), qalGetInteger(AL_EAX_RAM_FREE) * (1.0f / 1048576.0f));
	else
		Com_Printf("EAX-RAM not available\n");
#endif
	Com_Printf("\n");
}


/*
 ==============================================================================

    CONFIG REGISTRATION

 ==============================================================================
*/


void S_RegisterConfig ()
{
	s_alDriver = CVar_Register("s_alDriver", "", CVAR_STRING, CVAR_ARCHIVE | CVAR_LATCH, "AL driver", 0, 0);
	s_deviceName = CVar_Register("s_deviceName", "", CVAR_STRING, CVAR_ARCHIVE | CVAR_LATCH, "Sound device name", 0, 0);
	s_voiceCapture = CVar_Register("s_voiceCapture", "0", CVAR_BOOL, CVAR_ARCHIVE | CVAR_LATCH, "Enable voice capture", 0, 0);
	s_captureDeviceName = CVar_Register("s_captureDeviceName", "", CVAR_STRING, CVAR_ARCHIVE | CVAR_LATCH, "Sound capture device name", 0, 0);

	s_logFile = CVar_Register("s_logFile", "0", CVAR_INTEGER, CVAR_CHEAT, "Number of frames to log AL calls", 0, 0);
	s_ignoreALErrors = CVar_Register("s_ignoreALErrors", "1", CVAR_BOOL, CVAR_CHEAT, "Ignore AL errors", 0, 0);

	s_playDefaultSound = CVar_Register("s_playDefaultSound", "1", CVAR_BOOL, CVAR_ARCHIVE | CVAR_LATCH, "Play a beep for missing sounds", 0, 0);
	s_soundQuality = CVar_Register("s_soundQuality", "1", CVAR_INTEGER, CVAR_ARCHIVE | CVAR_LATCH, "Sound quality (0 = low, 1 = medium, 2 = high)", 0, 2);
	s_maxChannels = CVar_Register("s_maxChannels", "64", CVAR_INTEGER, CVAR_ARCHIVE | CVAR_LATCH, "Maximum number of mixing channels", 32, MAX_SOUND_CHANNELS);

	Cmd_AddCommand("listSoundDevices", S_ListSoundDevices_f);
	Cmd_AddCommand("listSoundCaptureDevices", S_ListSoundCaptureDevices_f);
	Cmd_AddCommand("sfxInfo", S_SfxInfo_f);
}

/*
 ==================
 S_UnregisterConfig
 ==================
*/
void S_UnregisterConfig ()
{
	Cmd_RemoveCommand("listSoundDevices");
	Cmd_RemoveCommand("listSoundCaptureDevices");
	Cmd_RemoveCommand("sfxInfo");
}


/*
 ==============================================================================

    INITIALIZATION AND SHUTDOWN

 ==============================================================================
*/


void S_Init (bool all)
{
	Com_Printf("-------- Sound Initialization --------\n");

	if (all)
	{
		S_RegisterConfig();

		ALImp_Init();
	}

	snd.soundMemoryPool = Mem_RegisterPool("Sound: Sound system");

	S_InitSounds();
	S_InitChannels();

	if (!s_ignoreALErrors->integerValue)
		S_CheckForErrors();

	Com_Printf("--------------------------------------\n");
}

void S_Shutdown (bool all)
{
	if (!alConfig.initialized)
		return;

	S_ShutdownChannels();
	S_ShutdownSounds();

	if (all)
	{
		S_UnregisterConfig();

		ALImp_Shutdown();
	}

	Mem_FreePool(snd.soundMemoryPool);

	memset(&snd, 0, sizeof(sndGlobals_t));
}